// 用户自定义的窗口api交互js文件 (在渲染进程运行的 但是可以用node.js)

import { shell, ipcRenderer } from 'electron';
import * as fs from 'fs';
import * as path from 'path';
import json5 from 'json5';
import propertie from 'properties-parser';
import { v4 as uuidv4 } from 'uuid';
import * as fse from 'fs-extra/esm';
import d123pan from './d123pan';
import AdmZip from 'adm-zip';



/**
 * 获取软件运行根目录
 * @returns 
 */
export function getMainPath() {
    if (process.env['ELECTRON_RENDERER_URL']) {
        // 开发模式
        return path.join(__dirname, '../../');
    }
    return path.join(__dirname, '../../../../');
}

/**
 * 调用外部浏览器打开网页
 * @param {string} url 
 */
export function openUrl(url) {
    shell.openExternal(url);
}

/**
 * 启动一个frp
 * @param {string} uuid 
 */
export function runFrp(uuid) {
    return new Promise(resolve => {
        let frpcPath = (() => {
            if (process.env['ELECTRON_RENDERER_URL']) {
                // 开发模式
                return path.join(__dirname, '../../resources/');
            }
            return path.join(__dirname, '../../../../resources/app.asar.unpacked/resources/');
        })();
        let configPath = path.join(getMainPath(), 'datas/frps/', uuid + '.ini');
        //调用启动服务器(携带参数用数组)
        ipcRenderer.invoke('createProcess', uuid, ['frpc.exe', '-c', configPath], frpcPath).then(res => {
            if (!res) {
                resolve(false);
                return;
            }
            resolve(true);
        }).catch(err => {
            resolve(true);
        });
    });
}

/**
 * 获取指定uuid的日志
 * @param {string} uuid 
 */
export function getFrpLog(uuid){
    let frpcPath = (() => {
        if (process.env['ELECTRON_RENDERER_URL']) {
            // 开发模式
            return path.join(__dirname, '../../resources/');
        }
        return path.join(__dirname, '../../../../resources/app.asar.unpacked/resources/');
    })();
    let logPath = path.join(frpcPath,'logs',uuid,'consoleLog.log');
    if (!fs.existsSync(logPath)) {
        return Promise.resolve('');
    }
    return new Promise((resolve, reject) => {
        fs.readFile(logPath, 'utf8', (err, data) => {
            if (err) {
                reject(err);
                return;
            }
            resolve(data);
        });
    });
}

/**
 * 删除指定uuid的日志
 * @param {string} uuid 
 */
export function delFrpLog(uuid){
    let frpcPath = (() => {
        if (process.env['ELECTRON_RENDERER_URL']) {
            // 开发模式
            return path.join(__dirname, '../../resources/');
        }
        return path.join(__dirname, '../../../../resources/app.asar.unpacked/resources/');
    })();
    let logPath = path.join(frpcPath,'logs',uuid);
    if (!fs.existsSync(logPath)) {
        return Promise.resolve(true); 
    }
    
    return new Promise((resolve, reject) => {
        fse.remove(logPath, err => {
            if (err) {
                resolve(false);
                return;
            }
            resolve(true);
        });
    });
}

/**
 * 新建一个frp
 * @returns 
 */
export function newFrp() {
    let newUuid = 'frp-' + uuidv4();//获取一个唯一的 uuid
    let pathstr = path.join(getMainPath(), 'datas/frps', newUuid + '.ini');
    let pathPar = path.parse(pathstr);
    if (!fs.existsSync(pathPar.dir)) fs.mkdirSync(pathPar.dir, { recursive: true });
    if (fs.existsSync(pathstr)) {
        return false;
    }
    fs.writeFileSync(pathstr, `[common]\nserver_addr = 0.0.0.0\nserver_port = 7000`);
    return newUuid;
}

/**
 * 获取指定frp配置
 * @param {string} uuid 
 */
export function getFrpConfig(uuid){
    let pathstr = path.join(getMainPath(), 'datas/frps', uuid + '.ini');
    if (!fs.existsSync(pathstr)) {
        return '';
    }
    return fs.readFileSync(pathstr,'utf8');
}


/**
 * 写入指定frp配置
 * @param {string} uuid 
 * @param {string} text 
 * @returns 
 */
export function setFrpConfig(uuid,text){
    let pathstr = path.join(getMainPath(), 'datas/frps', uuid + '.ini');
    if (!fs.existsSync(pathstr)) {
        let pathDir = path.parse(pathstr);
        fs.mkdirSync(pathDir.dir, { recursive: true });//创建目录
    }
    fs.writeFileSync(pathstr,text);
}

/**
 * 删除指定frp文件
 * @param {string} uuid 
 * @returns 
 */
export function delFrp(uuid) {
    return new Promise((resolve) => {
        // 删除日志
        delFrpLog(uuid);
        let pathstr = path.join(getMainPath(), 'datas/frps', uuid + '.ini');
        if (!fs.existsSync(pathstr)) {
            resolve(true);
            return;
        }
        fs.unlink(pathstr, (err) => {
            if (err) {
                resolve(false);
                return;
            }
            resolve(true)
        });
    });
}

/**
 * 解压压缩包到指定路径（覆盖解压）
 * @param {string} zipPath 压缩包文件的路径
 * @param {string} outputPath 被解压的目标文件夹路径
 * @returns 
 */
export function extractArchive(zipFilePath, outputDir) {
    return new Promise((resolve, reject) => {
        const zip = new AdmZip(zipFilePath);
        zip.extractAllToAsync(outputDir, true, (error) => {
            if (error) {
                reject(false);
            } else {
                resolve(true);
            }
        });
    });
}

/**
 * 打开指定目录
 * @param {string} directoryPath 
 */
export function explorerCatalog(directoryPath) {
    if (!path.isAbsolute(directoryPath)) {
        // 不是绝对路径 就转成绝对路径
        directoryPath = path.join(getMainPath(), directoryPath);
    }
    return new Promise((resolve, reject) => {
        // 使用 Electron 的 shell 模块打开目录
        shell.openPath(directoryPath)
            .then(() => {
                resolve(true);
            })
            .catch((err) => {
                resolve(false);
            });
    });
}

/**
 * 获取配置的信息
 * @returns 
 */
export function getSetting() {
    let paths = path.join(getMainPath(), './datas/setting.json');
    console.log('配置路径:',paths);
    if (!fs.existsSync(paths)) {
        return null;
    }
    let setting = fs.readFileSync(paths, 'utf8');
    try {
        return json5.parse(setting);
    } catch (error) {
        return false;
    }
}

/**
 * 初始化设置配置文件（可覆盖）
 */
export function initSetting(newData = null) {
    let settingPath = path.join(getMainPath(), './datas/setting.json');
    if (newData == null) {
        let directory = path.join(getMainPath(), './datas/items');
        let dirresBundle = path.join(getMainPath(), './datas/resBundle');//资源包
        isMkdir(directory);//目录不存在自动创建
        isMkdir(dirresBundle);//目录不存在自动创建
        newData = {
            // 这是目录地址
            directory,//项目列表
            powerBoot: false,//是否开机自启
        };
    }
    fs.writeFileSync(settingPath, JSON.stringify(newData, null, ' '));
}

/**
 * 判断指定资源包是否存在
 * @param {string} uuid 
 */
export function isAssignRes(uuid) {
    let dirresBundle = path.join(getMainPath(), './datas/resBundle', `${uuid}.zip`);//资源包
    return fs.existsSync(dirresBundle);
}

/**
 * 判断指定资源包是否存在
 * @param {string} uuid 
 */
export function getAssignResPath(uuid) {
    return path.join(getMainPath(), './datas/resBundle', `${uuid}.zip`);//资源包
}

/**
 * 初始化第一次（文件不存在 才创建）
 */
export function oneinitSetting() {
    let settingPath = path.join(getMainPath(), './datas/setting.json');
    if (!fs.existsSync(settingPath)) {
        initSetting();//创建新的
    }
}

/**
 * 如果目录（文件夹）不存在就创建它
 * @param {*} Path 
 */
export function isMkdir(Path) {
    if (!fs.existsSync(Path)) {
        // 如果目录不存在就创建文件夹
        fs.mkdirSync(Path, { recursive: true });
    }
}

/**
 * 设置是否开机自启
 * @param {*} status 
 */
export function setOpenRun(status = false) {
    ipcRenderer.send('user_setOpenRun', status);
}

/**
 * 获取json信息转对象
 * @returns 
 */
export function getJson(paths) {
    if (Array.isArray(paths)) {
        paths = path.join(...paths);
    }
    if (!path.isAbsolute(paths)) {
        // 不是绝对路径 就转成绝对路径
        paths = path.join(getMainPath(), paths);
    }
    if (!fs.existsSync(paths)) {
        return null;
    }
    let setting = fs.readFileSync(paths, 'utf8');
    try {
        return json5.parse(setting);
    } catch (error) {
        return false;
    }
}

/**
 * 获取文本信息
 * @returns 
 */
export function getFileText(paths) {
    if (Array.isArray(paths)) {
        paths = path.join(...paths);
    }
    if (!path.isAbsolute(paths)) {
        // 不是绝对路径 就转成绝对路径
        paths = path.join(getMainPath(), paths);
    }
    if (!fs.existsSync(paths)) {
        return '';
    }
    return fs.readFileSync(paths, 'utf8');
}


/**
 * 写入文本内容
 * @param {string} paths 
 * @param {string} text 
 * @returns 
 */
export function setFileText(paths, text) {
    if (Array.isArray(paths)) {
        paths = path.join(...paths);
    }
    if (!path.isAbsolute(paths)) {
        // 不是绝对路径 就转成绝对路径
        paths = path.join(getMainPath(), paths);
    }
    return fs.writeFileSync(paths, String(text));
}


/**
 * 设置对象转json
 * @param {string} paths 
 * @param {object} obj 
 * @returns 
 */
export function setJson(paths, obj) {
    if (Array.isArray(paths)) {
        paths = path.join(...paths);
    }
    if (!path.isAbsolute(paths)) {
        // 不是绝对路径 就转成绝对路径
        paths = path.join(getMainPath(), paths);
    }
    try {
        let newJson = JSON.stringify(obj, null, ' ');
        return fs.writeFileSync(paths, newJson);
    } catch (error) {
        return false;
    }
}



/**
 * 以桌面的默认方式打开给定的文件。
 * @param {*} directoryPath 
 */
export function openExternal(directoryPath) {
    if (!path.isAbsolute(directoryPath)) {
        // 不是绝对路径 就转成绝对路径
        directoryPath = path.join(getMainPath(), directoryPath);
    }
    shell.openExternal(directoryPath);
}


/**
 * 打开选择目录的弹窗
 * @returns 
 */
export function showOpenDialog(type = true, filters = []) {
    return ipcRenderer.invoke('user_showOpenDialog', type, filters);
}


/**
 * 获取项目列表
 */
export async function getItemList() {
    let Setting = getSetting();
    if(Setting==null) return null;
    let itemsPath = Setting.directory;
    if (!fs.existsSync(itemsPath)) return [];
    let itemList = fl(itemsPath, true);
    let newList = [];
    for (let { name } of itemList) {
        let configPath = path.join(itemsPath, name, './project-yoyo.json');//配置文件的路径
        if (!fs.existsSync(configPath)) continue;//不存在的路径
        let projectText = getJson(configPath);
        if (projectText.uuid != name) continue;//id和文件夹不同（这样可以过滤相同id不同文件夹的避免出现id重复的问题）
        projectText.path = path.join(itemsPath, name);//设置该服务器的运行目录
        projectText.isRun = await ipcRenderer.invoke('isRunProcess', projectText.uuid);//检查是否在运行
        projectText.createTime = parseInt(projectText.createTime) || 0;//格式化时间戳

        newList.push(projectText);
    }
    newList.sort((a, b) => {
        // 先比较 isRun 字段，将 isRun 为 true 的元素排在前面
        if (a.isRun && !b.isRun) {
            return -1;
        } else if (!a.isRun && b.isRun) {
            return 1;
        }
        // 当 isRun 相同时，比较 createTime 字段，按照从大到小排序
        return b.createTime - a.createTime;
    });
    return newList;
}

/**
 * 获取指定项目的信息
 * @param {string} uuid 
 */
export async function getItemInfo(uuid) {
    let Setting = getSetting();
    let itemsPath = Setting.directory;
    let configPath = path.join(itemsPath, uuid, './project-yoyo.json');//配置文件的路径
    if (!fs.existsSync(configPath)) return false;//不存在的路径(项目不存在)
    let projectText = getJson(configPath);
    if (projectText.uuid != uuid) return false;//id和文件夹不同（这样可以过滤相同id不同文件夹的避免出现id重复的问题）
    projectText.path = path.join(itemsPath, projectText.uuid);//设置该服务器的运行目录
    projectText.isRun = await ipcRenderer.invoke('isRunProcess', projectText.uuid);//检查是否在运行
    projectText.createTime = parseInt(projectText.createTime) || 0;//格式化时间戳
    return projectText;
}

/**
 * 新建一个新项目
 * @param {string} name 项目名称
 * @param {string} type 项目类型
 * @param {string} PackagevPath （包压缩包路径）
 */
export async function createItem(name, type, PackagevPath, coding = 'UTF8') {
    let Setting = getSetting();
    let itemsPath = Setting.directory;
    let newUuid = uuidv4();//获取一个唯一的 uuid
    let configPath = path.join(itemsPath, newUuid, './project-yoyo.json');//配置文件的路径
    let pathDir = path.parse(configPath).dir;
    let projectYoyo = {
        name,//名字
        uuid: newUuid,
        type,//类型
        start: '',
        stop: '',
        config: '',
        createTime: Date.now(),
        activeTime: Date.now(),//活跃时间
        autorun: false,//是否自动启动
        coding//编码
    };
    if (type == 'console') {
        // 控制器创建空应用
        isMkdir(pathDir);
        fs.writeFileSync(configPath, JSON.stringify(projectYoyo, null, ' '));// 写入配置
        return { status: true };
    }

    if (!PackagevPath) return { status: false, msg: '资源包不存在' };
    isMkdir(pathDir);//创建目录
    // 解压压缩包到目录
    let extStatus = await extractArchive(PackagevPath, pathDir);
    if (!extStatus) {
        return { status: false, msg: '资源包解压失败！' };
    }

    if (fs.existsSync(configPath)) {
        // 如果资源包已经有了配置文件（就读取修改）
        let oldprojectYoyo = getJson(configPath);
        if (oldprojectYoyo) {
            // 是正确的才可以设置覆盖
            projectYoyo = { ...projectYoyo, ...oldprojectYoyo };
        }
    }

    projectYoyo.uuid = newUuid;
    projectYoyo.name = name;
    projectYoyo.createTime = Date.now();
    projectYoyo.activeTime = Date.now();
    projectYoyo.autorun = false;
    if (!projectYoyo.type && type == 'sharePack') {
        // 没有类型设置默认控制台的
        projectYoyo.type = 'console';
    }
    fs.writeFileSync(configPath, JSON.stringify(projectYoyo, null, ' '));// 写入配置
    return { status: true };
}

/**
 * 解析123云盘直连
 * @param {string} url 
 */
export function d123panparse(url, pwd = null) {
    return new Promise((resolve) => {
        d123pan(url, pwd).then(res => {
            if (res.code != 0) {
                // 解析失败
                resolve({ status: false });
                return;
            }
            resolve({ status: true, data: res.data.redirect_url });
        });
    });
}

/**
 * 删除指定uuid项目
 * @param {string} uuid 
 */
export function delectItem(uuid) {
    let Setting = getSetting();
    let itemsPath = Setting.directory;
    let dirPath = path.join(itemsPath, uuid);//目录的路径
    return new Promise((resolve) => {
        fse.remove(dirPath, err => {
            if (err) {
                resolve(false);
                return;
            }
            resolve(true);
        });
    });
}

/**
 * 把properties文件格式转成对象
 * @param {*} paths 
 */
export function getProperties(paths) {
    if (Array.isArray(paths)) {
        paths = path.join(...paths);
    }
    if (!fs.existsSync(paths)) return false;//不存在的路径
    let text = fs.readFileSync(paths, 'utf8');
    try {
        return propertie.parse(text);
    } catch (error) {
        return false;
    }
}

/**
 * 把对象文件转成properties文件写入
 * @param {*} paths 
 * @param {*} obj 
 */
export function setProperties(paths, obj) {
    if (Array.isArray(paths)) {
        paths = path.join(...paths);
    }
    try {
        let texts = [];
        for (let key in obj) {
            texts.push(`${key}=${obj[key]}`);
        }
        fs.writeFileSync(paths, texts.join('\n'));
    } catch (error) {
        return false;
    }
    return true;
}



/**
 * 获取指定运行项目下面的控制台日志
 * @param {*} pathStr 
 * @returns 
 */
export function getLog(pathStr) {
    let logPath = path.join(pathStr, 'logs', 'consoleLog.log');
    if (!fs.existsSync(logPath)) {
        return Promise.resolve('');
    }
    return new Promise((resolve, reject) => {
        fs.readFile(logPath, 'utf8', (err, data) => {
            if (err) {
                reject(err);
                return;
            }
            resolve(data);
        });
    });
}

/**
* 获取指定目录下所有文件
* @param {String} path 
* @param {boolean} type 不传 返回所有  true返回文件夹  false 返回文件 
* @returns {Object}
*/
export function fl(path, type = null) {
    if (!fs.existsSync(path)) return [];//返回空的
    let ArrMu = fs.readdirSync(path, { withFileTypes: true });
    if (type === null) {
        return ArrMu;//返回所有
    } else if (type) {
        return ArrMu.filter(it => it.isDirectory());//返回目录
    } else {
        return ArrMu.filter(it => it.isFile());//返回文件
    }
}